package service_sys

import (
	"context"
	"errors"
	"fmt"
	"go_web/internal/model/model_sys"
	"go_web/internal/repo/repo_sys"
	"go_web/internal/req/req_sys"
	"go_web/internal/res/res_sys"
	"go_web/pkg/req"
	"go_web/pkg/res"
	"go_web/pkg/utils"
	"math"

	"github.com/fatih/structs"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"github.com/samber/lo"
	"gorm.io/gen"
	"gorm.io/gen/field"
)

type SysRouteService struct{}

// 创建新的 SysRouteService
func NewSysRouteService() *SysRouteService {
	return &SysRouteService{}
}

// 分页查询
func (*SysRouteService) Page(c context.Context, pageReq req_sys.SysRoutePageReq) (*res.PageRes, error) {
	offset := (pageReq.Page - 1) * pageReq.PageSize
	q := repo_sys.SysRoute.WithContext(c)

	// 排序处理
	if pageReq.SortField != nil {
		sortField := utils.ConvertToSnakeCase(*pageReq.SortField)
		orderFieldExpr := field.NewUnsafeFieldRaw(sortField)
		if pageReq.SortOrder != nil {
			if *pageReq.SortOrder == "asc" {
				q = q.Order(orderFieldExpr.Asc())
			} else {
				q = q.Order(orderFieldExpr.Desc())
			}
		} else {
			q = q.Order(orderFieldExpr.Asc())
		}
	}

	// 执行分页查询
	list, count, err := q.FindByPage(offset, pageReq.PageSize)
	if err != nil {
		return nil, err
	}

	// 计算总页数
	page := res.PageRes{
		List:     list,
		Total:    count,
		Page:     pageReq.Page,
		PageSize: pageReq.PageSize,
		Pages:    int64(math.Ceil(float64(count) / float64(pageReq.PageSize))),
	}

	return &page, nil
}

// 添加 SysRoute
func (*SysRouteService) Add(c context.Context, addReq req_sys.SysRouteAddReq) (int64, error) {
	var SysRoute model_sys.SysRoute
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := tx.SysRoute.WithContext(c)
		err := copier.Copy(&SysRoute, &addReq)
		if err != nil {
			return err
		}
		err = q.Create(&SysRoute)
		if err != nil {
			return err
		}

		if SysRoute.Type == 1 {
			// 0 目录 1 菜单 2 按钮
			// 菜单 => 加四个默认的按钮权限
			err := addDefaultButton(c, tx, SysRoute.ID, SysRoute.Name)
			if err != nil {
				return fmt.Errorf("异步错误【添加四个默认安全权限】 => ", err.Error())
			}
		}
		return nil
	})
	if err != nil {
		return 0, err
	}

	return SysRoute.ID, nil
}

type BtnPair struct {
	Name       string
	Permission string
}

func addDefaultButton(c context.Context, tx *repo_sys.Query, parentId int64, name string) error {
	var sysRoutes []*model_sys.SysRoute = make([]*model_sys.SysRoute, 0)
	var btnPairList []*BtnPair = make([]*BtnPair, 0)
	btnPairList = append(btnPairList, &BtnPair{
		Name:       "增加",
		Permission: name + ":add",
	})
	btnPairList = append(btnPairList, &BtnPair{
		Name:       "删除",
		Permission: name + ":delete",
	})
	btnPairList = append(btnPairList, &BtnPair{
		Name:       "编辑",
		Permission: name + ":edit",
	})
	btnPairList = append(btnPairList, &BtnPair{
		Name:       "查看",
		Permission: name + ":view",
	})
	for _, btnPair := range btnPairList {
		var sysRoute *model_sys.SysRoute = &model_sys.SysRoute{
			Name:       btnPair.Name,
			ParentId:   parentId,
			Permission: btnPair.Permission,
			Type:       2, // 按钮
		}
		sysRoutes = append(sysRoutes, sysRoute)
	}
	err := tx.SysRoute.WithContext(c).CreateInBatches(sysRoutes, 100)
	if err != nil {
		return err
	}
	// 所有角色默认都有这些按钮权限
	dictList, err := tx.SysDictDatum.WithContext(c).Where(tx.SysDictDatum.DictType.Eq("ROLE")).Find()
	if err != nil {
		return err
	}
	for _, dict := range dictList {
		var sysRoleAuthList []*model_sys.SysRouteAuth = make([]*model_sys.SysRouteAuth, 0)
		for _, sysRoute := range sysRoutes {
			var sysRouteAuth *model_sys.SysRouteAuth = &model_sys.SysRouteAuth{
				IsAccess:   true,
				RouteId:    sysRoute.ID,
				TargetType: "ROLE",
				Role:       dict.DictCode,
			}
			sysRoleAuthList = append(sysRoleAuthList, sysRouteAuth)
		}
		err = tx.SysRouteAuth.WithContext(c).CreateInBatches(sysRoleAuthList, 100)
		if err != nil {
			return err
		}
	}
	return nil
}

// 编辑 SysRoute 已开启事务
func (*SysRouteService) Edit(c context.Context, editReq req_sys.SysRouteEditReq) (int64, error) {
	var result gen.ResultInfo
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := tx.SysRoute.WithContext(c).Where(repo_sys.SysRoute.ID.Eq(editReq.ID))
		SysRoute, err := q.First()
		if err != nil {
			return err
		}
		err = copier.Copy(&SysRoute, &editReq)
		if err != nil {
			return err
		}
		result, err = q.Updates(structs.Map(SysRoute))
		if err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		if utils.IsOptimisticLockError(err) {
			return -1, nil // 乐观锁报错（版本不一致）
		}
		return 0, err
	}
	return result.RowsAffected, nil
}

// 删除 SysRoute
func (*SysRouteService) Delete(c context.Context, idsReq req.IdsReq) (int64, error) {
	var ret int64
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := tx.SysRoute.WithContext(c)
		ids, err := idsReq.ToInt64Slice()
		if err != nil {
			ret = 0
			return err
		}
		sysUserList, err := q.FindRouteTreeByRoots(ids)
		if err != nil {
			ret = 0
			return err
		}
		result, err := q.Delete(sysUserList...)
		if err != nil {
			ret = 0
			return err
		}
		ret = result.RowsAffected
		// 再去删除相关的 权限
		sysRouteAuthList, err := tx.SysRouteAuth.Where(tx.SysRouteAuth.RouteID.In(ids...)).Find()
		if err != nil {
			ret = 0
			return err
		}
		_, err = tx.SysRouteAuth.Delete(sysRouteAuthList...)
		if err != nil {
			ret = 0
			return err
		}
		return nil
	})
	return ret, err
}

// 查看 SysRoute 详情
func (*SysRouteService) Detail(c context.Context, userId int64) (*model_sys.SysRoute, error) {
	q := repo_sys.SysRoute.WithContext(c)
	SysRoute, err := q.Where(repo_sys.SysRoute.ID.Eq(userId)).First()
	if err != nil {
		return nil, err
	}
	return SysRoute, nil
}

// 获取动态路由树列表
func (s *SysRouteService) GetRouteTree(c context.Context) ([]*res_sys.SysRouteRes, error) {
	// 1. 安全获取 gin.Context
	ginCtx, ok := c.(*gin.Context)
	if !ok {
		return nil, errors.New("invalid context type")
	}

	// 2. 获取token和用户信息
	token, err := utils.GetTokenFromHeader(ginCtx)
	if err != nil {
		return nil, err
	}

	roleList, err := utils.GetRoleListByToken(c, *token)
	if err != nil {
		return nil, err
	}

	userId, err := utils.GetUserIdFromToken(*token)
	if err != nil {
		return nil, err
	}

	// 3. 获取所有路由
	sysRouteList, err := repo_sys.SysRoute.FindRouteTree()
	if err != nil {
		return nil, err
	}

	// 4. 构建路由映射
	routeMap := make(map[int64]*res_sys.SysRouteRes)
	for i := range sysRouteList {
		sysRouteRes := &res_sys.SysRouteRes{}
		if err := copier.Copy(sysRouteRes, &sysRouteList[i]); err != nil {
			return nil, fmt.Errorf("copy route data failed: %w", err)
		}
		routeMap[sysRouteList[i].ID] = sysRouteRes
	}

	// 5. 确定有权限的路由ID集合
	var authorizedRouteIDs map[int64]bool
	if lo.Contains(roleList, "ADMIN") {
		// ADMIN拥有所有路由权限
		authorizedRouteIDs = make(map[int64]bool)
		for _, route := range sysRouteList {
			authorizedRouteIDs[route.ID] = true
		}
	} else {
		// 普通用户根据权限筛选
		sysRouteAuthList, err := repo_sys.SysRouteAuth.FindEffectiveAuthList(userId, roleList)
		if err != nil {
			return nil, err
		}

		authorizedRouteIDs = make(map[int64]bool)
		for _, auth := range sysRouteAuthList {
			if auth.IsAccess {
				authorizedRouteIDs[auth.RouteId] = true
			}
		}
	}

	// 6. 构建路由树
	result := []*res_sys.SysRouteRes{}
	for _, sysRoute := range sysRouteList {
		if !authorizedRouteIDs[sysRoute.ID] {
			continue
		}

		vo := routeMap[sysRoute.ID]
		if sysRoute.ParentId == 0 {
			// 顶级节点
			result = append(result, vo)
		} else {
			// 非顶级节点
			parent := routeMap[sysRoute.ParentId]
			if parent != nil {
				if sysRoute.Type == 2 {
					// 按钮权限
					if parent.PermissionList == nil {
						parent.PermissionList = []*res_sys.PermissionRes{}
					}
					permissionRes := &res_sys.PermissionRes{}
					if err := copier.Copy(permissionRes, sysRoute); err != nil {
						continue // 或记录日志
					}
					parent.PermissionList = append(parent.PermissionList, permissionRes)
				} else {
					// 菜单或目录
					if parent.Children == nil {
						parent.Children = []*res_sys.SysRouteRes{}
					}
					parent.Children = append(parent.Children, vo)
				}
			}
		}
	}

	return result, nil
}
